package com.efrei.schoolmanager.views;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.List;
import java.util.Set;

import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.efrei.schoolmanager.controlers.ControleurClasse;
import com.efrei.schoolmanager.model.ModeleJListEleves;
import com.efrei.schoolmanager.model.obj.Classe;
import com.efrei.schoolmanager.model.obj.Eleve;
import com.efrei.schoolmanager.views.components.CustomButton;
import com.efrei.schoolmanager.views.components.CustomTextField;

public class VueEditerElevesClasse extends JDialog {
	private static final long serialVersionUID = 5043444073964549976L;

	private final static String TITLE = "Editer les eleves d'une classe";

	private final VueEditerElevesClasse vueActuelle;
	// Controleur
	private final ControleurClasse controleur;

	/* Panels */
	private JPanel mainPanel, titlePanel, elevesClassePanel, middlePanel,
			elevesPanel, validationPanel, classePanel, centerPanel;
	/* Labels */
	private JLabel titleLabel, classeLabel, elevesClasseLabel, elevesLabel;
	/* Zones de textes mono-ligne */
	private CustomTextField classeTextField;

	/* Boutons */
	private CustomButton ajouterEleveButton, retirerEleveButton, validerButton;

	/* Listes */
	private JList elevesClasseList, elevesList;
	private JScrollPane elevesClasseScroll, elevesScroll;

	/* Classe a modifier */
	private final Classe currentClasse;

	public VueEditerElevesClasse(VueListerClasse proprio,
			ControleurClasse controleur) {
		super(proprio.getFrame(), TITLE, true);
		this.controleur = controleur;
		vueActuelle = this;
		this.addWindowListener(new QuitterDialogListener());
		currentClasse = controleur.getCurrentClasse();
		/* Composants */
		initLabels();
		initTextFields();
		initButtons();
		initList();
		remplirTitlePanel();
		remplirMiddlePanel();
		remplirClassePanel();
		remplirValidationPanel();
		remplirEleveClassePanel();
		remplirMatieresGeneralesPanel();
		remplirCenterPanel();
		remplirMainPanel();

		/* Panel principal */
		initContentPane();

		/* Frame */
		configurerVue();
	}

	public void showDialog() {
		setVisible(true);
	}

	private void configurerVue() {
		pack();
		this.setLocationRelativeTo(null);
		this.showDialog();
	}

	private void initContentPane() {
		setLayout(new BorderLayout());
		add(mainPanel, BorderLayout.CENTER);
		add(titlePanel, BorderLayout.NORTH);
	}

	private void initLabels() {
		titleLabel = new JLabel(TITLE);
		titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
		classeLabel = new JLabel("Classe:");
		elevesLabel = new JLabel("Eleves disponibles");
		elevesClasseLabel = new JLabel("Eleves de la classe");
	}

	private void initTextFields() {
		/* Text fields */
		classeTextField = new CustomTextField(currentClasse.toString(),
				new Dimension(180, 25));
		classeTextField.setEditable(false);

	}

	private void initButtons() {
		/* Listeners */
		AjouterEleveButtonListener ajouterEleveListener = new AjouterEleveButtonListener();
		RetirerEleveButtonListener retirerEleveListener = new RetirerEleveButtonListener();
		ValiderButtonListener validerListener = new ValiderButtonListener();
		ajouterEleveButton = new CustomButton("Ajouter élève");
		ajouterEleveButton.addActionListener(ajouterEleveListener);
		ajouterEleveButton.setEnabled(false);
		retirerEleveButton = new CustomButton("Retirer élève");
		retirerEleveButton.addActionListener(retirerEleveListener);
		retirerEleveButton.setEnabled(false);
		validerButton = new CustomButton("Valider");
		validerButton.addActionListener(validerListener);
	}

	private void initList() {
		EleveClasseListListener elevesClasseListener = new EleveClasseListListener();
		ElevesListListener elevesListener = new ElevesListListener();
		elevesClasseList = new JList(new ModeleJListEleves());
		elevesList = new JList(new ModeleJListEleves());
		elevesClasseScroll = new JScrollPane(elevesClasseList);
		elevesScroll = new JScrollPane(elevesList);

		// Ajout des listeners
		elevesClasseList.addListSelectionListener(elevesClasseListener);
		elevesList.addListSelectionListener(elevesListener);

		/* Recuperer eleves */
		Set<Eleve> elevesClasse = currentClasse.getEleves();
		List<Eleve> eleves = controleur.getEleves();

		/* Recuperer les modeles */
		ModeleJListEleves modeleElevesClasse = (ModeleJListEleves) elevesClasseList
				.getModel();
		ModeleJListEleves modeleEleves = (ModeleJListEleves) elevesList
				.getModel();
		/* Remplir les listes */
		// Eleves de la classe
		for (Eleve eleveClasse : elevesClasse) {
			modeleElevesClasse.addEleve(eleveClasse);
		}
		// Eleves disponibles
		for (Eleve eleve : eleves) {
			if (!elevesClasse.contains(eleve))
				modeleEleves.addEleve(eleve);
		}

		// Contraindre la selection à une seule valeur à la fois
		elevesClasseList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		elevesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		// Modifier la taille des listes
		Dimension d = new Dimension(260, 180);
		elevesClasseScroll.setPreferredSize(d);
		elevesScroll.setPreferredSize(d);
	}

	private void remplirClassePanel() {
		classePanel = new JPanel();
		classePanel.add(classeLabel);
		classePanel.add(classeTextField);
	}

	private void remplirValidationPanel() {
		validationPanel = new JPanel();
		validationPanel.add(validerButton);
	}

	private void remplirTitlePanel() {
		titlePanel = new JPanel();
		titlePanel.add(titleLabel);
	}

	private void remplirMiddlePanel() {
		middlePanel = new JPanel();
		GroupLayout gl = new GroupLayout(middlePanel);
		middlePanel.setLayout(gl);
		// Espacement des composants
		gl.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		gl.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles horizontalement
		/* 1e colonne */
		hGroup.addGroup(gl.createParallelGroup()
				.addComponent(ajouterEleveButton)
				.addComponent(retirerEleveButton));
		gl.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles verticalement
		/* 1e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(ajouterEleveButton));
		/* 2e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(retirerEleveButton));
		gl.setVerticalGroup(vGroup);
	}

	private void remplirEleveClassePanel() {
		elevesClassePanel = new JPanel();
		GroupLayout gl = new GroupLayout(elevesClassePanel);
		elevesClassePanel.setLayout(gl);
		// Espacement des composants
		gl.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		gl.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles horizontalement
		/* 1e colonne */
		hGroup.addGroup(gl.createParallelGroup()
				.addComponent(elevesClasseLabel)
				.addComponent(elevesClasseScroll));
		gl.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles verticalement
		/* 1e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(elevesClasseLabel));
		/* 2e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(elevesClasseScroll));
		gl.setVerticalGroup(vGroup);
	}

	private void remplirMatieresGeneralesPanel() {
		elevesPanel = new JPanel();
		GroupLayout gl = new GroupLayout(elevesPanel);
		elevesPanel.setLayout(gl);
		// Espacement des composants
		gl.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		gl.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles horizontalement
		/* 1e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(elevesLabel)
				.addComponent(elevesScroll));
		gl.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles verticalement
		/* 1e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(elevesLabel));
		/* 2e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(elevesScroll));
		gl.setVerticalGroup(vGroup);
	}

	private void remplirCenterPanel() {
		centerPanel = new JPanel();
		centerPanel.add(elevesPanel);
		centerPanel.add(middlePanel);
		centerPanel.add(elevesClassePanel);
	}

	private void remplirMainPanel() {
		mainPanel = new JPanel();
		mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
		mainPanel.add(classePanel);
		mainPanel.add(centerPanel);
		mainPanel.add(validationPanel);
	}

	/**
	 * Ferme la fenetre et libere les ressources
	 * 
	 */
	public void fermerVue() {
		this.setVisible(false);
		this.dispose();

	}

	/* Listeners */
	class AjouterEleveButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			// Recuperation des modeles
			ModeleJListEleves modeleEleves = (ModeleJListEleves) elevesList
					.getModel();
			ModeleJListEleves modeleElevesClasse = (ModeleJListEleves) elevesClasseList
					.getModel();
			// Recuperation des donnees
			Eleve nouvelEleveClasse = (Eleve) elevesList.getSelectedValue();

			// Mise à jour des listes
			modeleElevesClasse.addEleve((nouvelEleveClasse));
			modeleEleves.removeEleve(elevesList.getSelectedIndex());
			// Mise à jour de la base
			Set<Eleve> elevesClasse = currentClasse.getEleves();
			elevesClasse.add(nouvelEleveClasse);
		}
	}

	class RetirerEleveButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			// Recuperation des modeles
			ModeleJListEleves modeleEleves = (ModeleJListEleves) elevesList
					.getModel();
			ModeleJListEleves modeleElevesClasse = (ModeleJListEleves) elevesClasseList
					.getModel();
			// Recuperation des donnees
			Eleve eleveSupprimeClasse = (Eleve) elevesClasseList
					.getSelectedValue();

			// Mise à jour des listes
			modeleEleves.addEleve((eleveSupprimeClasse));
			modeleElevesClasse.removeEleve(elevesClasseList.getSelectedIndex());
			// Mise à jour de la base
			Set<Eleve> elevesClasse = currentClasse.getEleves();
			elevesClasse.remove(eleveSupprimeClasse);

		}

	}

	class ValiderButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			vueActuelle.fermerVue();
		}

	}

	class ElevesListListener implements ListSelectionListener {

		@Override
		public void valueChanged(ListSelectionEvent e) {
			if (!e.getValueIsAdjusting()) {

				if (elevesList.getSelectedIndex() == -1) {
					// Aucun eleve selectionne, masquer le bouton d'ajout
					ajouterEleveButton.setEnabled(false);

				} else {
					// Un eleve selectionne, afficher le bouton d'ajout
					ajouterEleveButton.setEnabled(true);
				}
			}
		}

	}

	class EleveClasseListListener implements ListSelectionListener {
		@Override
		public void valueChanged(ListSelectionEvent e) {
			if (!e.getValueIsAdjusting()) {
				if (elevesClasseList.getSelectedIndex() == -1) {
					// Aucun eleve selectionne, masquer le bouton de retrait
					retirerEleveButton.setEnabled(false);

				} else {
					// Un eleve selectionne, afficher le bouton de retrait
					retirerEleveButton.setEnabled(true);
				}
			}
		}

	}

	class QuitterDialogListener implements WindowListener {

		@Override
		public void windowActivated(WindowEvent e) {

		}

		@Override
		public void windowClosed(WindowEvent e) {
		}

		@Override
		public void windowClosing(WindowEvent e) {
			vueActuelle.fermerVue();
		}

		@Override
		public void windowDeactivated(WindowEvent e) {

		}

		@Override
		public void windowDeiconified(WindowEvent e) {

		}

		@Override
		public void windowIconified(WindowEvent e) {

		}

		@Override
		public void windowOpened(WindowEvent e) {

		}

	}
}
